package com.palmgo.utils.drawer.basic;

import java.util.ArrayList;
import java.util.List;

import javafx.scene.Scene;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.palmgo.utils.drawer.model.ConvertFactors;
import com.palmgo.utils.drawer.model.DrawInfo;
import com.palmgo.utils.drawer.model.LatLng;
import com.palmgo.utils.drawer.model.RectF;
import com.palmgo.utils.drawer.model.RoadType;
import com.palmgo.utils.drawer.model.Segment;
import com.palmgo.utils.drawer.model.TrafficSegment;
import com.palmgo.utils.drawer.model.Vetrux;
import com.palmgo.utils.drawer.model.ZipUtils;

/**
 * 掌城道路路况绘制工具
 *
 * @author tanqiyong
 */
public class DeformationAgient {
	private static Logger LOG = LoggerFactory.getLogger(DeformationAgient.class);
    
	/**
	 * 图像的边距
	 */
	private final int ROAD_GRAPHIC_INTERVAL_DEF = 40;
	/**
	 * 额定总绘图区域
	 */
	private final int ROAD_GRAPHIC_WIDTH_DEF = 560;
	
	private final int PADDING = 40;
	/**
	 * 道路的宽度
	 */
	private int ROAD_GRAPHIC_LINE_WIDTH = 30;
	/**
	 * 图像的边距
	 */
	private float ROAD_GRAPHIC_INTERVAL = 40;
	/**
	 * 额定总绘图区域
	 */
	private float ROAD_GRAPHIC_WIDTH = 560;
	/**
	 * 额定中心图像区域
	 */
	private float ROAD_GRAPHIC_WIDTH_NOINTERVAL = ROAD_GRAPHIC_WIDTH
			- ROAD_GRAPHIC_INTERVAL * 2;
	private static float FONTSIZE_DEF = 24;
	private String unZipdata;
	private byte[] zipdata;

	private Segment segment;
	// 双向整条路
	private List<Segment> froadList;
	private List<Segment> rroadList;

	private int width;
	private int height;
	private float fontSize = 18;
	private int roadWidth = 40;
	private List<LatLng> locations;
	private double direction;
	private boolean bottomCenter = false;
	private RoadType roadType = RoadType.DOUBLE;
	GraphicsContext context;
	 /** 变量:背景颜色,类型:Color */
    private Color backColor = Color.color(35d / 256, 37d / 256, 55d / 256);
	 /** 变量:图片名称,类型:String */
    private String pngName;
    
	public DeformationAgient() {
	}

	public void setData(String unZipdata) {
		this.unZipdata = unZipdata;
	}

	public void setData(byte[] zipdata) {
		this.zipdata = zipdata;
	}

	public void setData(Segment segment) {
		this.segment = segment;
	}

	public void setData(List<Segment> froadList, List<Segment> rroadList) {
		this.froadList = froadList;
		this.rroadList = rroadList;
	}


	public void setFontSize(float fontSize) {
		this.fontSize = fontSize;
	}

	public void setRoadWidth(int roadWidth) {
		this.roadWidth = roadWidth;
	}

	public void setLocations(List<LatLng> locations) {
		this.locations = locations;
	}

	public void setDirection(double direction) {
		this.direction = direction;
	}

	public void setNeedBottomCenter(boolean bottomCenter) {
		this.bottomCenter = bottomCenter;
	}

	public void setRoadType(RoadType roadType) {
		this.roadType = roadType;
	}

	//
	// public WritableImage convert() {
	// try {
	// width = bitmap.getWidth();
	// height = bitmap.getHeight();
	// if (width <= 0 || height <= 0) {
	// // 图片不正确，无法绘制
	// return bitmap;
	// }
	// //判断数据类型
	// if (zipdata != null) {
	// drawByZipdata();
	// } else if (!TextUtils.isEmpty(unZipdata)) {
	// drawByUnZipdata();
	// } else if (segment != null) {
	// drawByPath();
	// } else if (froadList != null && rroadList != null) {
	// drawByAllRoad();
	// }
	//
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// return bitmap;
	// }

	/**
	 * 获取属性 pngName的值
	 * @return the pngName : String
	 */
	public String getPngName() {
		return pngName;
	}

	/**
	 * 设置属性pngName的值，参数类型String
	 * @param pngName the pngName to set
	 */
	public void setPngName(String pngName) {
		this.pngName = pngName;
	}

	public WritableImage convert(Scene scene, GraphicsContext gc) {
		try {
			gc.beginPath();
			width = (int) scene.getWidth();
			height = (int) scene.getHeight();
			if (width <= 0 || height <= 0) {
				// 图片不正确，无法绘制
				return null;
			}
			context = gc;
            context.clearRect(0, 0, scene.getWidth(),scene.getHeight());
            context.setFill(backColor);
            context.fillRect(0, 0,scene.getWidth(),scene.getHeight());
            context.beginPath();
			// 判断数据类型
			if (zipdata != null) {
				drawByZipdata();
			} else if (!isEmpty(unZipdata)) {
				drawByUnZipdata();
			} else if (segment != null) {
				drawByPath();
			} else if (froadList != null && rroadList != null) {
				drawByAllRoad();
			}
			return scene.snapshot(null);
		} catch (Exception e) {
        	LOG.error("绘制单张图片异常,pngName="+getPngName(),e);
            return null;
        }

	}

	void drawByZipdata() {
		try {
			String data = "";
			if (zipdata != null) {
				data = ZipUtils.unZip(zipdata);
			}
			if (isEmpty(data))
				return;
			if (roadType == RoadType.SINGLE) {
				createFrontRoadBmp(data);
			} else {
				createRoadBmp(data);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	void drawByUnZipdata() {
		if (isEmpty(unZipdata))
			return;
		if (roadType == RoadType.SINGLE) {
			createFrontRoadBmp(unZipdata);
		} else {
			createRoadBmp(unZipdata);
		}
	}

	void drawByPath() {
		createPathOfLineBmp(segment, 0);
	}

	void drawByAllRoad() {
		createAllOfLineBmp(froadList, rroadList, 0);
	}

	protected static class LocationVetrux {
		LatLng location;
		double minDis1;
		int index1;
		double minDis2;
		int index2;

		public LocationVetrux(LatLng location) {
			this.location = location;
		}
	}

	private void createFrontRoadBmp(String data) {
		// try {
		// List<GraphicTrafficEntity> datas = JSON2BeanUtils.comperJson2List(
		// new JSONArray(data), GraphicTrafficEntity.class);
		// for (GraphicTrafficEntity b : datas) {
		// String[] coord = b.coord.split(",");
		// double lat = Double.valueOf(coord[1]);
		// double lng = Double.valueOf(coord[0]);
		// b.pt = new LatLng(lat, lng);
		// if (b.froadBean != null) {
		// b.froadBean.traffic_status =
		// formatTrafficStatus(b.froadBean.traffic_status);
		// }
		// if (b.rroadBean != null) {
		// b.rroadBean.traffic_status =
		// formatTrafficStatus(b.rroadBean.traffic_status);
		// }
		// }
		// boolean isRroadDirction = true;
		// // 计算所有需要绘制的点
		// // 记录下距离最近的点
		// if (locations != null && locations.size() > 0) {
		// // 获取所有距离最近的两个点，用以确定一条线
		// LatLng curLL = locations.get(0);
		// LocationVetrux p = new LocationVetrux(curLL);
		// // 找出它到每个点的距离，
		// for (int j = 0; j < datas.size(); j++) {
		// LatLng l1 = datas.get(j).pt;
		// double dLat = curLL.latitude - l1.latitude;
		// double dLng = curLL.longitude - l1.longitude;
		// double dis = Math.sqrt(dLat * dLat + dLng * dLng);
		// if (j == 0) {
		// p.minDis1 = dis;
		// p.index1 = j;
		// } else if (j == 1) {
		// p.minDis2 = dis;
		// p.index2 = j;
		// } else if (dis < p.minDis1 || dis < p.minDis2) {
		// if (p.minDis1 < p.minDis2) {
		// p.minDis2 = dis;
		// p.index2 = j;
		// } else {
		// p.minDis1 = dis;
		// p.index1 = j;
		// }
		//
		// }
		// }
		// // 计算到道路起点的距离，如果越来越远，则是正向
		// LatLng fll = locations.get(0);
		// LatLng ell = locations.get(locations.size() - 1);
		// LatLng lineStartLL = datas.get(0).pt;
		// double llat1 = fll.latitude - lineStartLL.latitude;
		// double llong1 = fll.longitude - lineStartLL.longitude;
		// double disL = Math.sqrt(llat1 * llat1 + llong1 * llong1);
		// double llat2 = ell.latitude - lineStartLL.latitude;
		// double llong2 = ell.longitude - lineStartLL.longitude;
		// double disF = Math.sqrt(llat2 * llat2 + llong2 * llong2);
		// if (disF <= disL) {
		// // 远离的方向，更新远的点
		// int pos = Math.min(p.index1, p.index2);
		// datas.get(pos).pt = locations.get(0);
		// datas = datas.subList(pos, datas.size());
		// } else {
		// int pos = Math.max(p.index1, p.index2);
		// datas.get(pos).pt = locations.get(0);
		// if (pos + 1 < datas.size()) {
		// pos++;
		// }
		// datas = datas.subList(0, pos);
		// isRroadDirction = false;
		// }
		// } else {
		// // 数据不够时，需要用方向判断isRroadDirction
		// LatLng sp = datas.get(0).pt;
		// LatLng ep = datas.get(datas.size() - 1).pt;
		// double roadDegrees = Math.toDegrees(Math.atan2(ep.latitude
		// - sp.latitude, ep.longitude - sp.longitude));
		// double carDegrees = 90 - roadDegrees;// 因为行车方向正北为0，坐标轴正东为0
		// if (Math.abs(carDegrees - direction) <= 90) {
		// isRroadDirction = true;
		// } else {
		// isRroadDirction = false;
		// }
		// }
		// // 计算角度
		// if (locations != null && locations.size() > 1) {
		// LatLng firstOne = locations.get(locations.size() - 1);
		// LatLng lastOne = locations.get(0);
		// double dy = lastOne.latitude - firstOne.latitude;
		// double dx = lastOne.longitude - firstOne.longitude;
		// direction = Math.toDegrees(Math.atan2(dy, dx));
		// if (dx < 0) {
		// direction = -270 - direction;
		// } else {
		// direction = 90 - direction;
		// }
		// }
		//
		// // 将数据组装成需要的格式
		// List<Segment> rroad = new ArrayList<Segment>();
		// Segment item;
		// for (int i = 0; i < datas.size() - 1; i++) {
		// GraphicTrafficEntity curObj = datas.get(i);
		// GraphicTrafficEntity nextObj = datas.get(i + 1);
		// if (curObj.rroadBean == null) {
		// // 获取最后一个数据，将节点放入队尾,如果没有节点，不处理数据
		// if (rroad.size() > 0) {
		// item = rroad.get(rroad.size());
		// item.pts.add(curObj.pt);
		// if (nextObj.rroadBean != null) {
		// item.endname = curObj.segmentname;
		// item.pts.add(nextObj.pt);
		// }
		// }
		// } else {
		// // curObj.rroadBean != null,将新元素加入队列中
		// item = new Segment();
		// item.pts.add(curObj.pt);
		// item.startname = curObj.segmentname;
		// item.trafficlistBeans.add(curObj.rroadBean);
		// // 如果两个连续，直接结束当前元素
		// if (nextObj.rroadBean != null) {
		// item.endname = nextObj.segmentname;
		// item.pts.add(nextObj.pt);
		// }
		// if (i == datas.size() - 2) {
		// item.endname = nextObj.segmentname;
		// item.pts.add(nextObj.pt);
		// }
		// rroad.add(item);
		// }
		// }
		// List<Segment> froad = new ArrayList<Segment>();
		// for (int i = datas.size() - 1; i > 0; i--) {
		// GraphicTrafficEntity curObj = datas.get(i);
		// GraphicTrafficEntity nextObj = datas.get(i - 1);
		// if (curObj.froadBean == null) {
		// // 获取最后一个数据，将节点放入队尾,如果没有节点，不处理数据
		// if (froad.size() > 0) {
		// item = froad.get(froad.size());
		// item.pts.add(curObj.pt);
		// if (nextObj.froadBean != null) {
		// item.endname = curObj.segmentname;
		// item.pts.add(nextObj.pt);
		// }
		// }
		// } else {
		// // curObj.froadBean != null,将新元素加入队列中
		// item = new Segment();
		// item.pts.add(curObj.pt);
		// item.startname = curObj.segmentname;
		// item.trafficlistBeans.add(curObj.froadBean);
		// // 如果两个连续，直接结束当前元素
		// if (nextObj.froadBean != null) {
		// item.endname = nextObj.segmentname;
		// item.pts.add(nextObj.pt);
		// }
		// if (i == 1) {
		// item.endname = nextObj.segmentname;
		// item.pts.add(nextObj.pt);
		// }
		// froad.add(item);
		// }
		// }
		// // 2.解析数据
		// return createDefineLineBmp(isRroadDirction ? rroad : froad);
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
	}

	private String formatTrafficStatus(String status) {
		try {
			if (status.contains("畅")) {
				return "C";
			} else if (status.contains("缓")) {
				return "B";
			} else if (status.contains("堵")) {
				return "A";
			}
		} catch (Exception e) {
		}
		return "N";
	}

	/**
	 * 生成双向行驶的道路路况，数据来源于道路，如：北四环
	 *
	 * @return
	 */
	private void createRoadBmp(String data) {
		// try {
		// List<GraphicTrafficEntity> datas = JSON2BeanUtils.comperJson2List(
		// new JSONArray(data), GraphicTrafficEntity.class);
		// for (GraphicTrafficEntity b : datas) {
		// String[] coord = b.coord.split(",");
		// int lat = (Double.valueOf(coord[1]) * 1e6);
		// int lng = (Double.valueOf(coord[0]) * 1e6);
		// b.pt = new LatLng(lat, lng);
		// if (b.froadBean != null) {
		// b.froadBean.traffic_status =
		// formatTrafficStatus(b.froadBean.traffic_status);
		// }
		// if (b.rroadBean != null) {
		// b.rroadBean.traffic_status =
		// formatTrafficStatus(b.rroadBean.traffic_status);
		// }
		// }
		// // 将数据组装成需要的格式
		// List<Segment> rroad = new ArrayList<Segment>();
		// List<Segment> froad = new ArrayList<Segment>();
		// Segment item;
		// int size = datas.size();
		// for (int i = 0; i < size; i++) {
		// GraphicTrafficEntity curObj = datas.get(i);
		// if (curObj.rroadBean != null) {
		// item = new Segment();
		// item.pts.add(curObj.pt);
		// if (rroad.isEmpty())
		// item.startname = curObj.segmentname;
		// else
		// item.endname = curObj.segmentname;
		// item.trafficlistBeans.add(curObj.rroadBean);
		// rroad.add(item);
		// }
		// if (curObj.froadBean != null) {
		// item = new Segment();
		// item.pts.add(curObj.pt);
		// if (froad.isEmpty())
		// item.startname = curObj.segmentname;
		// else
		// item.endname = curObj.segmentname;
		// item.trafficlistBeans.add(curObj.froadBean);
		// froad.add(item);
		// }
		// }
		// // 2.解析数据
		// return createAllOfLineBmp(froad, rroad, 0);
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
	}

	/**
	 * 绘制整条路段 <br>
	 * 耗时计算，建议开启异步线程
	 *
	 * @param froad
	 *            正向路况数据
	 * @return
	 */
	protected void createPathOfLineBmp(Segment froad, double routeAngle) {
		try {
			if (roadWidth > 0) {
				ROAD_GRAPHIC_LINE_WIDTH = roadWidth;
			}
			initScale(width, height);
			List<Vetrux> m_vectors1 = new ArrayList<Vetrux>();
			List<TrafficSegment> m_traffic_segments1 = new ArrayList<TrafficSegment>();
			ConvertFactors factors = new ConvertFactors();
			/** 正向 */
			DrawInfo drawinfo = new DrawInfo();
			// 解析折线编码
			DecodeUtils.decodePoly(segment.coords, segment.pts);
			makingShowArea(segment.pts, factors);
			for (Segment.Traffic traffic : segment.trafficlistBeans) {
				drawinfo.arrRoadCondition.add(traffic.traffic_status);
			}
			// 计算坐标转换因子
			calcCoordinateFactorByCity(factors, width, height);
			// 转化坐标，并得到绘制点信息
			DrawInfo.Flag flag = new DrawInfo.Flag(true);
			getConvertCoordsByCity(segment, drawinfo, factors, flag);
			// 计算旋转角
			calcRouteByCity(drawinfo, width, height, routeAngle);
			// ==========END=======基础数据处理完成
			// 生成segment
			addTrafficSegement(drawinfo, m_vectors1, m_traffic_segments1, true);
			// 去重，将数据封入segment
			rebuild_traffic_segment(m_traffic_segments1,
					TrafficGraphic.segment_outline_type_e.down_segment_outline);
			// 生成绘制道路所用数据
			List<Line> lines1 = new ArrayList<Line>(m_vectors1.size() - 1);
			calcRouteParams(m_vectors1, m_traffic_segments1,
					ROAD_GRAPHIC_LINE_WIDTH / 2, lines1);
			// 绘制路段路况
			TrafficGraphic.draw_traffic_flow(context, m_traffic_segments1);
			if (fontSize <= 0) {
				fontSize = FONTSIZE_DEF;
			}
			List<RectF> textRects = new ArrayList<RectF>();
			List<TextParam> textParams1 = new ArrayList<TextParam>();
			List<TextParam> textParams2 = new ArrayList<TextParam>();
			calcTextFlowParams(m_traffic_segments1, lines1, textParams1);
			// 文字去重
			rebuildTextFlowParams(textParams1, textParams2);
			draw_text_flow(context, textParams1, textRects, m_vectors1,
					m_traffic_segments1);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 绘制整条路段 <br>
	 * 耗时计算，建议开启异步线程
	 *
	 * @param froad
	 *            正向路况数据
	 * @param rroad
	 *            反向路况数据
	 * @return
	 */
	protected void createAllOfLineBmp(List<Segment> froad, List<Segment> rroad,
			double routeAngle) {
		try {
			if (roadWidth > 0) {
				ROAD_GRAPHIC_LINE_WIDTH = roadWidth;
			}
			initScale(width, height);
			List<Vetrux> m_vectors1 = new ArrayList<Vetrux>();
			List<TrafficSegment> m_traffic_segments1 = new ArrayList<TrafficSegment>();
			List<Vetrux> m_vectors2 = new ArrayList<Vetrux>();
			List<TrafficSegment> m_traffic_segments2 = new ArrayList<TrafficSegment>();
			ConvertFactors factors = new ConvertFactors();
			/** 正向 */
			DrawInfo positiveDrawInfo = new DrawInfo();
			// /** 反向 */
			DrawInfo reverseDrawInfo = new DrawInfo();
			// 解析折线编码
			getRoadConditionByCity(froad, positiveDrawInfo, factors);
			getRoadConditionByCity(rroad, reverseDrawInfo, factors);
			// 计算坐标转换因子
			calcCoordinateFactorByCity(factors, width, height);
			// 转化坐标，并得到绘制点信息
			getConvertCoordsByCity(froad, positiveDrawInfo, factors);
			getConvertCoordsByCity(rroad, reverseDrawInfo, factors);
			// 计算旋转角
			calcRouteByCity(positiveDrawInfo, width, height, routeAngle);
			calcRouteByCity(reverseDrawInfo, width, height, routeAngle);
			// ==========END=======基础数据处理完成
			// 生成segment
			addTrafficSegement(positiveDrawInfo, m_vectors1,
					m_traffic_segments1, true);
			addTrafficSegement(reverseDrawInfo, m_vectors2,
					m_traffic_segments2, false);
			// 去重，将数据封入segment
			rebuild_traffic_segment(m_traffic_segments1,
					TrafficGraphic.segment_outline_type_e.down_segment_outline);
			// 生成绘制道路所用数据
			List<Line> lines1 = new ArrayList<Line>(m_vectors1.size() - 1);
			List<Line> lines2 = new ArrayList<Line>(m_vectors1.size() - 1);
			calcRouteParams(m_vectors1, m_traffic_segments1,
					ROAD_GRAPHIC_LINE_WIDTH / 2, lines1);
			rebuild_traffic_segment(m_traffic_segments2,
					TrafficGraphic.segment_outline_type_e.down_segment_outline);
			calcRouteParams(m_vectors2, m_traffic_segments2,
					ROAD_GRAPHIC_LINE_WIDTH / 2, lines2);
			// 绘制路段路况
			TrafficGraphic.draw_traffic_flow(context, m_traffic_segments1);
			TrafficGraphic.draw_traffic_flow(context, m_traffic_segments2);
			if (fontSize <= 0) {
				fontSize = FONTSIZE_DEF;
			}

			List<RectF> textRects = new ArrayList<RectF>();
			List<TextParam> textParams1 = new ArrayList<TextParam>();
			List<TextParam> textParams2 = new ArrayList<TextParam>();
			calcTextFlowParams(m_traffic_segments1, lines1, textParams1);
			calcTextFlowParams(m_traffic_segments2, lines2, textParams2);
			// 文字去重
			rebuildTextFlowParams(textParams1, textParams2);
			List<TrafficSegment> segments = new ArrayList<TrafficSegment>(
					m_traffic_segments1.size() + m_traffic_segments2.size());
			segments.addAll(m_traffic_segments1);
			segments.addAll(m_traffic_segments2);
			draw_text_flow(context, textParams1, textRects, m_vectors1,
					segments);
			draw_text_flow(context, textParams2, textRects, m_vectors2,
					segments);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void rebuildTextFlowParams(List<TextParam> textParams1,
			List<TextParam> textParams2) {
		int len1 = textParams1.size();
		int mark = 0;// 如果使用i，i会因为i--而一直是同一列，计算结果有问题
		for (int i = 0; i < len1; i++) {
			String text1 = textParams1.get(i).text;
			for (TextParam p : textParams2) {
				if (p.text.equals(text1)) {
					if (mark % 2 == 0)
						textParams2.remove(p);
					else {
						textParams1.remove(i);
						i--;
						len1--;
					}
					mark++;
					break;
				}
			}
		}
	}

	private class TextParam {
		String text;
		Vetrux pt;
		Line line;

		protected TextParam(String text, Vetrux pt, Line line) {
			this.text = text;
			this.pt = pt;
			this.line = line;
		}
	}

	void calcTextFlowParams(List<TrafficSegment> segments, List<Line> lines,
			List<TextParam> texts) {
		if (segments == null || segments.isEmpty())
			return;
		int segLen = segments.size();
		for (int i = 0; i < segLen; i++) {
			TrafficSegment s = segments.get(i);
			if (s.downOutLine.isEmpty())
				continue;
			if (i == 0 && !isEmpty(s.startText)) {
				texts.add(new TextParam(s.startText, s.downOutLine.get(0),
						lines.get(0)));
			}
			if (!isEmpty(s.endText)) {
				texts.add(new TextParam(s.endText, s.downOutLine
						.get(s.downOutLine.size() / 2 - 1), lines
						.get(s.vertex_count - 1)));
			}
		}
	}

	void draw_text_flow(GraphicsContext context, List<TextParam> textParams,
			List<RectF> textRects, List<Vetrux> vectors,
			List<TrafficSegment> segments) {
		if(vectors.isEmpty()){
			LOG.warn("路名绘制集合为空，跳过.pngName="+getPngName());
			return;
		}
		try{
			Vetrux sp = vectors.get(0);
			Vetrux ep = vectors.get(vectors.size() - 1);
			double degress = Math.toDegrees(Math.atan2(ep.y - sp.y, ep.x - sp.x));
			TextDriction roadDriction = getTextDriction(degress);
			RectF box = new RectF(0, 0, width, height);
			for (TextParam param : textParams) {
				drawText(context, param.text, param.pt, param.line, roadDriction,
						box, textRects, segments, fontSize);
			}
		}catch(Exception e){
			LOG.error("绘制道路名称异常,pngName={},msg={}",getPngName(),e.getLocalizedMessage());
		}
	}

	/**
	 * 判断区域是否越界
	 *
	 * @param box
	 * @param r
	 * @return
	 */
	private boolean isIncludeBox(RectF box, RectF r) {
		return box.left <= r.left && box.top <= r.top && box.right >= r.right
				&& box.bottom >= r.bottom;
	}

	/**
	 * 判断文字区域是否和现有区域相交
	 *
	 * @param rs
	 * @param r
	 * @return
	 */
	private boolean interSect(List<RectF> rs, RectF r) {
		for (RectF r1 : rs) {
			double maxLeft = Math.max(r1.left, r.left);
			double maxTop = Math.max(r1.top, r.top);
			double minRight = Math.min(r1.right, r.right);
			double minBottom = Math.min(r1.bottom, r.bottom);
			if (maxLeft < minRight && maxTop < minBottom)
				return true;
		}
		return false;
	}

	private void drawText(GraphicsContext context, String text, Vetrux pt,
			Line l, TextDriction textDriction, RectF area,
			List<RectF> textRects, List<TrafficSegment> segments, float fontSize) {
		// 1.计算路段与X轴夹角
		// 2.获取文字的绘制方向
		// TextDriction driction = textDriction;
		TextDriction driction = getTextDriction(l.degress);
		// 3.获取文字区域
		RectF textRect = getTextRect(text, pt, fontSize, driction,
				0.6f * roadWidth);
		// 验证区域是否与现有区域重叠
		if (!isIncludeBox(area, textRect) || interSect(textRects, textRect)
				|| interRoad(segments, textRect)) {
			// 验证另一方向
			driction = getOtherTextDriction(driction);
			textRect = getTextRect(text, pt, fontSize, driction,
					0.6f * roadWidth);
			if (!isIncludeBox(area, textRect) || interSect(textRects, textRect)
					|| interRoad(segments, textRect))
				return;
		}
		context.setFont(Font.font("黑体", fontSize));
		context.setFill(Color.WHITE);
		// 如果文字垂直走向，需要每行绘制一个字
		if (driction == TextDriction.TOP_BOTTOM
				|| driction == TextDriction.BOTTOM_TOP) {
			int strLen = text.length();
			double textHeight = textRect.height() / strLen;
			for (int j = 0; j < strLen; j++) {
				String str = text.substring(j, j + 1);
				context.fillText(str, textRect.left, textRect.top + (j + 1)
						* textHeight);
			}
		} else {
			context.fillText(text, textRect.left, textRect.bottom);
		}
		// 绘制文字标记
		drawTextFlag(context, pt, roadWidth * 0.3f, driction);
		textRects.add(textRect);
	}

	private Boolean isLineIntersectRectangle(Vetrux v0, Vetrux v1,
			RectF textRect) {
		double lineWidth = v1.x - v0.x;
		double lineHeight = v0.y - v1.y; // 计算叉乘
		double c = v0.x * v1.y - v1.x * v0.y;
		if ((lineHeight * textRect.left + lineWidth * textRect.bottom + c <= 0 && lineHeight
				* textRect.right + lineWidth * textRect.top + c >= 0)
				|| (lineHeight * textRect.left + lineWidth * textRect.bottom
						+ c >= 0 && lineHeight * textRect.right + lineWidth
						* textRect.top + c <= 0)
				|| (lineHeight * textRect.left + lineWidth * textRect.top + c <= 0 && lineHeight
						* textRect.right + lineWidth * textRect.bottom + c >= 0)
				|| (lineHeight * textRect.left + lineWidth * textRect.top + c >= 0 && lineHeight
						* textRect.right + lineWidth * textRect.bottom + c <= 0)) {

			if ((v0.x < textRect.left && v1.x < textRect.left)
					|| (v0.x > textRect.right && v1.x > textRect.right)
					|| (v0.y < textRect.top && v1.y < textRect.top)
					|| (v0.y > textRect.bottom && v1.y > textRect.bottom)) {
				return false;
			} else {
				return true;
			}
		} else {
			return false;
		}
	}

	boolean isLineIntersectRectangle(double linePointX1, double linePointY1,
			double linePointX2, double linePointY2, double rectangleLeftTopX,
			double rectangleLeftTopY, double rectangleRightBottomX,
			double rectangleRightBottomY) {
		double lineHeight = linePointY1 - linePointY2;
		double lineWidth = linePointX2 - linePointX1; // 计算叉乘
		double c = linePointX1 * linePointY2 - linePointX2 * linePointY1;
		if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight
				* rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0)
				|| (lineHeight * rectangleLeftTopX + lineWidth
						* rectangleLeftTopY + c <= 0 && lineHeight
						* rectangleRightBottomX + lineWidth
						* rectangleRightBottomY + c >= 0)
				|| (lineHeight * rectangleLeftTopX + lineWidth
						* rectangleRightBottomY + c >= 0 && lineHeight
						* rectangleRightBottomX + lineWidth * rectangleLeftTopY
						+ c <= 0)
				|| (lineHeight * rectangleLeftTopX + lineWidth
						* rectangleRightBottomY + c <= 0 && lineHeight
						* rectangleRightBottomX + lineWidth * rectangleLeftTopY
						+ c >= 0)) {

			if (rectangleLeftTopX > rectangleRightBottomX) {
				double temp = rectangleLeftTopX;
				rectangleLeftTopX = rectangleRightBottomX;
				rectangleRightBottomX = temp;
			}
			if (rectangleLeftTopY < rectangleRightBottomY) {
				double temp1 = rectangleLeftTopY;
				rectangleLeftTopY = rectangleRightBottomY;
				rectangleRightBottomY = temp1;
			}
			if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX)
					|| (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX)
					|| (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY)
					|| (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY)) {
				return false;
			} else {
				return true;
			}
		} else {
			return false;
		}
	}

	/**
	 * 判断文字的矩形是否与道路相交
	 * 
	 * @param segments
	 * @param textRect
	 * @return
	 */
	private boolean interRoad(List<TrafficSegment> segments, RectF textRect) {
		for (TrafficSegment segment : segments) {
			Vetrux p1 = segment.downOutLine.get(0);
			Vetrux p2 = segment.downOutLine.get(segment.downOutLine.size() / 2);
			Vetrux p3 = segment.downOutLine
					.get((segment.downOutLine.size() + 1) / 2);
			Vetrux p4 = segment.downOutLine.get(segment.downOutLine.size() - 1);
			if (isLineIntersectRectangle(p1.x, p1.y, p2.x, p2.y, textRect.left,
					textRect.bottom, textRect.right, textRect.top)
					&& isLineIntersectRectangle(p3.x, p3.y, p4.x, p4.y,
							textRect.left, textRect.bottom, textRect.right,
							textRect.top))
				return true;
		}
		return false;
	}

	private void drawTextFlag(GraphicsContext context, Vetrux pt,
			float roadWidth, TextDriction driction) {
		switch (driction) {
		case TOP_BOTTOM:
			context.moveTo(pt.x, pt.y + roadWidth / 2);
			context.lineTo(pt.x - roadWidth / 2, pt.y + roadWidth * 3 / 2);
			context.lineTo(pt.x + roadWidth / 2, pt.y + roadWidth * 3 / 2);
			break;
		case BOTTOM_TOP:
			context.moveTo(pt.x, pt.y - roadWidth / 2);
			context.lineTo(pt.x - roadWidth / 2, pt.y - roadWidth * 3 / 2);
			context.lineTo(pt.x + roadWidth / 2, pt.y - roadWidth * 3 / 2);
			break;
		case LEFT_RIGHT:
			context.moveTo(pt.x + roadWidth / 2, pt.y);
			context.lineTo(pt.x + roadWidth * 3 / 2, pt.y - roadWidth / 2);
			context.lineTo(pt.x + roadWidth * 3 / 2, pt.y + roadWidth / 2);
			break;
		case RIGHT_LEFT:
			context.moveTo(pt.x - roadWidth / 2, pt.y);
			context.lineTo(pt.x - roadWidth * 3 / 2, pt.y - roadWidth / 2);
			context.lineTo(pt.x - roadWidth * 3 / 2, pt.y + roadWidth / 2);
			break;
		default:
			break;
		}
		context.closePath();
		// context.setFill(Color.TRANSPARENT);
		context.setStroke(Color.WHITE);
		context.stroke();
		// context.fill();
	}

	private RectF getTextRect(String text, Vetrux pt, float width,
			TextDriction driction, float offSet) {
		RectF result = new RectF();
		switch (driction) {
		case TOP_BOTTOM:// 从上至下显示
			result.set(pt.x - width / 2, pt.y + offSet, pt.x + width / 2, pt.y
					+ offSet + (width) * text.length());
			break;
		case BOTTOM_TOP:
			result.set(pt.x - width / 2,
					pt.y - offSet - (width) * text.length(), pt.x + width / 2,
					pt.y - offSet);
			break;
		case LEFT_RIGHT:
			result.set(pt.x + offSet, pt.y - width / 2, pt.x + offSet + (width)
					* text.length(), pt.y + width / 2);
			break;
		case RIGHT_LEFT:
			result.set(pt.x - offSet - (width) * text.length(), pt.y - width
					/ 2, pt.x - offSet, pt.y + width / 2);
			break;
		default:
			break;
		}
		return result;
	}

	/**
	 * 获取文字的绘制方向
	 *
	 * @param degress
	 * @return
	 */
	TextDriction getTextDriction(double degress) {
		if (degress >= -45 && degress <= 45) {
			return TextDriction.TOP_BOTTOM;
		} else if ((degress >= -180 && degress <= -135)
				|| (degress >= 135 && degress <= 180)) {
			return TextDriction.BOTTOM_TOP;
		} else if (degress > 45 && degress < 135) {
			return TextDriction.RIGHT_LEFT;
		} else if (degress > -135 && degress < -45) {
			return TextDriction.LEFT_RIGHT;
		}
		return TextDriction.LEFT_RIGHT;
	}

	/**
	 * 获取另一可显示方向
	 *
	 * @param driction
	 * @return
	 */
	TextDriction getOtherTextDriction(TextDriction driction) {
		switch (driction) {
		case LEFT_RIGHT:
			return TextDriction.TOP_BOTTOM;
		case TOP_BOTTOM:
			return TextDriction.LEFT_RIGHT;
		case BOTTOM_TOP:
			return TextDriction.RIGHT_LEFT;
		default:
			return TextDriction.BOTTOM_TOP;
		}
	}

	enum TextDriction {
		TOP_BOTTOM, BOTTOM_TOP, RIGHT_LEFT, LEFT_RIGHT
	}

	/**
	 * 
	 * @param vectors1
	 * @param segments
	 */
	void remoteVectx(List<Vetrux> vectors1, List<TrafficSegment> segments) {
		int delElems = 0;
		int start = 0;
		int end = 0;
		Vetrux lastVetrux = vectors1.get(vectors1.size() - 1);
		for (TrafficSegment seg : segments) {
			end = seg.vertex_count - delElems;
			for (int i = start; i < end; i++) {
				Vetrux p0 = vectors1.get(i);
				Vetrux p1 = vectors1.get(i + 1);
				if (p1 != lastVetrux
						&& TrafficGraphic.get_distance(p0, p1) < 40) {
					delElems++;
					vectors1.remove(i + 1);
					i--;
					end--;
				}
			}
			seg.vertex_count -= delElems;
			// 将下一节点的起点设置为此节点的终点
			start = seg.vertex_count;
		}
	}

	void calcRouteParams(List<Vetrux> vectors1, List<TrafficSegment> segments,
			int roadWidth, List<Line> lines) {
		if (vectors1 == null || vectors1.isEmpty())
			return;
		remoteVectx(vectors1, segments);
		int len = vectors1.size();
		List<Vetrux> vectors2 = new ArrayList<Vetrux>(len + 1);
		// 计算出拓宽的vectors
		// firstpt
		Vetrux lastPt = vectors1.get(0);
		Vetrux curPt = vectors1.get(1);
		Vetrux firstPt = calcRouteXVetrux(lastPt, curPt, roadWidth, true);
		// endpt
		lastPt = vectors1.get(len - 2);
		curPt = vectors1.get(len - 1);
		Vetrux endPt = calcRouteXVetrux(lastPt, curPt, roadWidth, false);
		// calc lines
		for (int i = 0; i < len - 1; i++) {
			Vetrux last = vectors1.get(i);
			Vetrux cur = vectors1.get(i + 1);
			lines.add(calcRouteDrig(last, cur, roadWidth));
		}
		// add vectors
		// add first
		vectors2.add(firstPt);
		// add others
		// calc 交点lines.size = vCount-1
		for (int i = 0; i < len - 2; i++) {
			Line l1 = lines.get(i);
			Line l2 = lines.get(i + 1);
			double sx = 0, sy = 0;
			if (!Double.isNaN(l1.a) && !Double.isNaN(l2.a)) {
				if (l1.degress == l2.degress) {
					// 与X平行，取原来的点的x作为x
					sx = vectors1.get(i + 1).x;
					sy = l1.a * sx + l1.b;
				} else {
					sx = (l2.b - l1.b) / (l1.a - l2.a);
					// y=ax+b
					sy = l1.a * sx + l1.b;
				}
			} else if (Double.isNaN(l1.a) && !Double.isNaN(l2.a)) {
				// x=b => sx=l1.b
				sx = l1.b;
				sy = l2.a * sx + l2.b;
			} else if (!Double.isNaN(l1.a) && Double.isNaN(l2.a)) {
				// x=b => sx=l2.b
				sx = l2.b;
				sy = l1.a * sx + l1.b;
			} else if (Double.isNaN(l1.a) && Double.isNaN(l2.a)) {
				// 与Y轴平行的两行线，没有交点，所以交点就是原点平移，lo是v0,v1的线，所以l(i)与l(i+1)的线
				// 交点是v(i+1)
				sx = l1.b;
				sy = vectors1.get(i + 1).y;
			}
			vectors2.add(new Vetrux(sx, sy));
		}
		// add end
		vectors2.add(endPt);
		// get endVector
		vectors2.add(getEndVector(endPt, vectors1.get(len - 1),
				lines.get(lines.size() - 1), roadWidth));
		/****** calc end **********/
		int cursor = 0;
		int segmentsLen = segments.size();
		for (int si = 0; si < segmentsLen; si++) {
			TrafficSegment segment = segments.get(si);
			int vCount = segment.vertex_count - cursor + 1;
			// 如果节点没有两个纬度无法绘图
			if (vCount < 2) {
				segments.remove(si--);
				segmentsLen--;
				continue;
			}
			segment.downOutLine.clear();
			for (int i = cursor; i <= segment.vertex_count; i++) {
				segment.downOutLine.add(vectors2.get(i));
			}
			// 判断是否为最后一项
			if (segment.vertex_count == vectors1.size() - 1)
				segment.downOutLine.add(vectors2.get(len));
			for (int i = segment.vertex_count; i >= cursor; i--) {
				segment.downOutLine.add(vectors1.get(i));
			}
			cursor = segment.vertex_count;
			// end
		}
	}

	private Vetrux getEndVector(Vetrux endPt, Vetrux endPt1, Line line,
			int roadWidth) {
		// 移动坐标y=ax，x2+y2=roadwidth2=>
		// ax*ax+x*x=roadWidth*roadWidth=>x=Math.sqre(roadWidth*roadWidth/(a*a+1))
		Vetrux p = new Vetrux();
		if (line.a == null) {
			// x=b
			p.set(endPt.x, endPt.y + roadWidth * (line.degress > 0 ? 1 : -1));
		} else {
			// 以endPt为原点，直线则为y=ax
			double degress = Math.toDegrees(Math.atan2(endPt1.y - endPt.y,
					endPt1.x - endPt.x));
			double s = degress <= 0 ? 1 : -1;
			double x = Math.sqrt(roadWidth * roadWidth / (line.a * line.a + 1))
					* s;
			// 基于endPt重新获得坐标值
			p.set((float) (endPt.x + x), (float) (endPt.y + line.a * x));
		}
		// 根据endPt1获取最终点
		return new Vetrux((endPt1.x + p.x) / 2, (endPt1.y + p.y) / 2);
	}

	// y=ax+b;
	private static class Line {
		Double a;
		// b=y-ax;
		double b;
		double degress;
	}

	Vetrux calcRouteXVetrux(Vetrux perviousPt, Vetrux curPt, double roadWidth,
			boolean first) {
		double detalY = curPt.y - perviousPt.y;
		double detalX = curPt.x - perviousPt.x;
		double dis = Math.sqrt(detalY * detalY + detalX * detalX);
		double x;
		double y;
		if (first) {
			x = perviousPt.x - detalY / dis * roadWidth;
			y = perviousPt.y + detalX / dis * roadWidth;
		} else {
			x = curPt.x - detalY / dis * roadWidth;
			y = curPt.y + detalX / dis * roadWidth;
		}
		// perviousPt在平行线上的垂点
		Vetrux firstPt = new Vetrux(x, y);
		return firstPt;
	}

	Line calcRouteDrig(Vetrux perviousPt, Vetrux curPt, double roadWidth) {
		double detalY = curPt.y - perviousPt.y;
		double detalX = curPt.x - perviousPt.x;
		double dis = Math.sqrt(detalY * detalY + detalX * detalX);
		double x = perviousPt.x - detalY / dis * roadWidth;
		double y = perviousPt.y + detalX / dis * roadWidth;
		// perviousPt在平行线上的垂点
		Vetrux firstPt = new Vetrux(x, y);
		Line line = new Line();
		line.degress = Math.toDegrees(Math.atan2(detalY, detalX));
		// 如果degress==90度，x=b
		if (detalX == 0) {
			line.a = Double.NaN;
			if (detalY == 0)
				line.b = perviousPt.x - roadWidth;
			else
				line.b = firstPt.x;
		} else {
			// y=ax+b
			line.a = detalY / detalX;
			line.b = firstPt.y - line.a * firstPt.x;
		}
		// System.err.println(perviousPt.toString());System.err.println(curPt.toString());
		// System.err.println(detalX+"////"+line.a+","+line.b);
		return line;
	}

	/**
	 * 计算旋转角
	 *
	 * @param positiveDrawInfo
	 */
	private void calcRouteByCity(DrawInfo positiveDrawInfo, int width,
			int height, double routeAngle) {
		try {
			Vetrux center = new Vetrux(width / 2, height / 2);
			for (DrawInfo.DrawInfoUnit item : positiveDrawInfo.arrDrawInfo) {
				double dx = item.x - center.x;
				double dy = center.y - item.y;
				double dis = Math.sqrt(dx * dx + dy * dy);// 点到中心点的半径
				double oldAngle = Math.toDegrees(Math.atan2(dy, dx));
				double angle = oldAngle + routeAngle;
				double fx = center.x + dis * Math.cos(Math.toRadians(angle));
				double fy = center.y - dis * Math.sin(Math.toRadians(angle));
				item.x = fx;
				item.y = fy;
			}
		} catch (Exception e) {
		}
	}

	/**
	 * 绘制路径规划路段 <br>
	 * 耗时计算，建议开启异步线程
	 *
	 * @return
	 */
	protected void createDefineLineBmp(List<Segment> segments) {
		try {
			ROAD_GRAPHIC_LINE_WIDTH = roadWidth;
			if (segments == null) {
				return;
			}
			initScale(width, height);
			List<Vetrux> m_vectors1 = new ArrayList<Vetrux>();
			List<TrafficSegment> m_traffic_segments1 = new ArrayList<TrafficSegment>();
			ConvertFactors factors = new ConvertFactors();
			/** 正向 */
			DrawInfo positiveDrawInfo = new DrawInfo();
			/** 反向 */
			getRoadConditionByCity(segments, positiveDrawInfo, factors);
			// 重新计算经纬度范围
			calcGraphictpBottomCenter(factors, locations, bottomCenter);
			// 计算坐标转换因子
			calcCoordinateFactorByCity(factors, width, height);
			// 转化坐标，并得到绘制点信息
			getConvertCoordsByCity(segments, positiveDrawInfo, factors);
			// 计算旋转角
			calcRouteByCity(positiveDrawInfo, width, height, direction);
			// Y轴平移图像
			calcGraphicLocation(width, height, positiveDrawInfo, bottomCenter);
			// ==========END=======基础数据处理完成
			// 绘制数据开始
			TrafficGraphic.segment_end_type_e se_type;
			addTrafficSegement(positiveDrawInfo, m_vectors1,
					m_traffic_segments1, true);
			//
			se_type = TrafficGraphic.segment_end_type_e.triangle_end_t;
			rebuild_traffic_segment(m_traffic_segments1,
					TrafficGraphic.segment_outline_type_e.down_segment_outline);
			TrafficGraphic.calc_traffic_segment_outline(m_vectors1,
					m_traffic_segments1,
					TrafficGraphic.segment_outline_type_e.down_segment_outline,
					ROAD_GRAPHIC_LINE_WIDTH, se_type);
			// 制作image
			// 绘制路段路况
			TrafficGraphic.draw_traffic_flow(context, m_traffic_segments1);
			RectF rbox = new RectF(0, 0, ROAD_GRAPHIC_WIDTH, ROAD_GRAPHIC_WIDTH);
			if (fontSize <= 0) {
				fontSize = FONTSIZE_DEF;
			}
			if (m_traffic_segments1.size() > 0) {
				TrafficGraphic.draw_traffic_text(context, m_vectors1,
						m_traffic_segments1, rbox, ROAD_GRAPHIC_LINE_WIDTH,
						fontSize);
			}
			// return bitmap;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 沿Y轴平移图片，使其底部居中
	 *
	 * @param width
	 * @param height
	 * @param positiveDrawInfo
	 * @param bottomCenter
	 */
	private void calcGraphicLocation(int width, int height,
			DrawInfo positiveDrawInfo, boolean bottomCenter) {
		if (!bottomCenter) {
			return;
		}
		try {
			// 获取纵坐标需要平移的量
			List<DrawInfo.DrawInfoUnit> infos = positiveDrawInfo.arrDrawInfo;
			double y1 = infos.get(0).y;
			double y2 = infos.get(infos.size() - 1).y;
			double y = Math.max(y1, y2);
			double distance = height - PADDING - y;
			for (DrawInfo.DrawInfoUnit unit : infos) {
				unit.y += distance;
			}
		} catch (Exception e) {
		}
	}

	/**
	 * 图片底部居中
	 *
	 * @param factors
	 * @param locations
	 */
	private void calcGraphictpBottomCenter(ConvertFactors factors,
			List<LatLng> locations, boolean bottomCenter) {
		try {
			if (!bottomCenter || locations == null || locations.size() == 0) {
				return;
			}
			// DOTO
			LatLng curPt = locations.get(0);
			double centerLng = (factors.maxLongitude + factors.minLongitude) / 2;
			if (centerLng < curPt.longitude) {
				factors.maxLongitude = 2 * curPt.longitude
						- factors.minLongitude;
			} else if (centerLng > curPt.longitude) {
				factors.minLongitude = 2 * curPt.longitude
						- factors.maxLongitude;
			}
		} catch (Exception e) {
		}
	}

	/**
	 * 解析折线编码
	 *
	 * @param segments
	 * @param drawinfo
	 */
	void getRoadConditionByCity(List<Segment> segments, DrawInfo drawinfo,
			ConvertFactors factors) {
		try {
			for (Segment segment : segments) {
				if(segment.coords!=null){
            		DecodeUtils.decodePoly(segment.coords, segment.pts);
            	}
				makingShowArea(segment.pts, factors);
				for (Segment.Traffic traffic : segment.trafficlistBeans) {
					drawinfo.arrRoadCondition.add(traffic.traffic_status);
				}
			}
		} catch (Exception e) {
			LOG.error("解析折线编码异常,msg="+e.getLocalizedMessage());
		}
	}

	/**
	 * 标记绘图范围
	 *
	 * @param pts
	 * @param factors
	 */
	void makingShowArea(List<LatLng> pts, ConvertFactors factors) {
		if (pts == null || pts.size() <= 0) {
			return;
		}
		if (factors.minLatitude == 0) {
			// 如果没有值，将第一项的值赋予它
			factors.minLatitude = pts.get(0).latitude;
			factors.maxLatitude = pts.get(0).latitude;
			factors.minLongitude = pts.get(0).longitude;
			factors.maxLongitude = pts.get(0).longitude;
		}
		for (LatLng pt : pts) {
			if (pt.latitude < factors.minLatitude) {
				factors.minLatitude = pt.latitude;
			} else if (pt.latitude > factors.maxLatitude) {
				factors.maxLatitude = pt.latitude;
			}
			if (pt.longitude < factors.minLongitude) {
				factors.minLongitude = pt.longitude;
			} else if (pt.longitude > factors.maxLongitude) {
				factors.maxLongitude = pt.longitude;
			}
		}
	}

	/**
	 * 计算绘图参数
	 *
	 * @param factors
	 */
	private void calcCoordinateFactorByCity(ConvertFactors factors, int width,
			int height) {
		// 计算Y跨度
		double disLatitude = factors.maxLatitude - factors.minLatitude;
		// 计算X跨度
		double disLongitude = factors.maxLongitude - factors.minLongitude;
		factors.xFactor = ROAD_GRAPHIC_WIDTH_NOINTERVAL / disLongitude;
		factors.yFactor = ROAD_GRAPHIC_WIDTH_NOINTERVAL / disLatitude;
		// 为了和IOS处理结果一样，需要对数据的小数位数进行处理
		factors.xFactor = Math.round(factors.xFactor * 1e11) / 1e11;
		factors.yFactor = Math.round(factors.yFactor * 1e11) / 1e11;
		// 获取缩放比例
		factors.factor = factors.xFactor < factors.yFactor ? factors.xFactor
				: factors.yFactor;
		// 获取图片的实际占用大小
		double actualWidth = disLongitude / factors.factor;
		double actualHei = disLatitude / factors.factor;
		// 确定起始坐标
		factors.showRect = new RectF((float) (width - actualWidth) / 2,
				(float) (height - actualHei) / 2,
				(float) (width + actualWidth) / 2,
				(float) (height + actualHei) / 2);

	}

	/**
	 * 将数据列表中的数据转入绘图对象中
	 *
	 * @param froad
	 * @param positiveDrawInfo
	 */
	private void getConvertCoordsByCity(List<Segment> froad,
			DrawInfo positiveDrawInfo, ConvertFactors factors) {
		try {
			DrawInfo.Flag flag = new DrawInfo.Flag(true);
			for (int i = 0; i < froad.size(); i++) {
				Segment segment = froad.get(i);
				getConvertCoordsByCity(segment, positiveDrawInfo, factors, flag);
			}
		} catch (Exception e) {
		}
	}

	/**
	 * 单个数据转为绘图数据
	 *
	 * @param segment
	 * @param positiveDrawInfo
	 * @param factors
	 * @param flag
	 */
	private void getConvertCoordsByCity(Segment segment,
			DrawInfo positiveDrawInfo, ConvertFactors factors,
			DrawInfo.Flag flag) {
		DrawInfo.DrawInfoUnit item;
		int ptsLen = segment.pts.size();
		for (int j = 0; j < ptsLen; j++) {
			LatLng p = segment.pts.get(j);
			item = new DrawInfo.DrawInfoUnit();
			if (j == 0 && ptsLen > 1 && flag.bFirst == false) {
				continue;
			}
			if (j == 0 && flag.bFirst) {
				// 第一个点
				item.sectionName = segment.getStartname();
				flag.bFirst = false;
			} else if (j == ptsLen - 1 && !flag.bFirst) {
				item.sectionName = segment.getEndname();
			}
			item.x = (float) ((p.longitude - factors.minLongitude)
					* factors.factor + ROAD_GRAPHIC_INTERVAL);
			int nInterval = 0;
			if (factors.xFactor > factors.factor) {
				nInterval = (int) ((ROAD_GRAPHIC_WIDTH_NOINTERVAL - (factors.maxLongitude - factors.minLongitude)
						* factors.factor) / 2);
				item.x += nInterval;
			}
			item.y = (float) ((p.latitude - factors.minLatitude)
					* factors.factor + ROAD_GRAPHIC_INTERVAL);
			item.y = ROAD_GRAPHIC_WIDTH - item.y;
			if (factors.yFactor > factors.factor) {
				nInterval = (int) ((ROAD_GRAPHIC_WIDTH_NOINTERVAL - (factors.maxLatitude - factors.minLatitude)
						* factors.factor) / 2);
				item.y -= nInterval;
			}
			positiveDrawInfo.arrDrawInfo.add(item);
		}
	}

	void addTrafficSegement(DrawInfo drawInfo, List<Vetrux> vectors,
			List<TrafficSegment> trafficSegments, boolean bPositive) {
		if (drawInfo == null || drawInfo.arrDrawInfo == null
				|| drawInfo.arrDrawInfo.size() == 0) {
			return;
		}
		String startName = "";
		String endName = "";
		String nRoadCondition = "";
		int listSize = drawInfo.arrDrawInfo.size();
		for (int i = 0; i < listSize; i++) {
			DrawInfo.DrawInfoUnit item = drawInfo.arrDrawInfo.get(i);
			if (i == 0) {
				// 添加节点
				vectors.add(new Vetrux(item.x, item.y));
				startName = item.sectionName;
			} else {
				if (i <= drawInfo.arrRoadCondition.size()) {
					nRoadCondition = drawInfo.arrRoadCondition.get(i - 1);
				} else {
					nRoadCondition = "0";
				}
				endName = item.sectionName;
				// 添加节点
				vectors.add(new Vetrux(item.x, item.y));
				add_traffic_segment(trafficSegments, vectors.size() - 1,
						nRoadCondition, nRoadCondition, nRoadCondition,
						startName, endName);
				//
				startName = endName;
			}
		}
	}

	static void add_traffic_segment(List<TrafficSegment> list,
			int vertex_count, String traffic_status, String up_traffic_status,
			String down_traffic_status, String startText, String endText) {
		TrafficSegment ts = new TrafficSegment();
		ts.vertex_count = vertex_count;
		ts.traffic_status = traffic_status;
		ts.up_traffic_status = up_traffic_status;
		ts.down_traffic_status = down_traffic_status;
		ts.startText = isEmpty(startText) ? "" : startText;
		ts.endText = isEmpty(endText) ? "" : endText;
		list.add(ts);
	}

	/**
	 * 数据整理，去重
	 *
	 * @param array
	 * @param type
	 */
	private void rebuild_traffic_segment(List<TrafficSegment> array,
			TrafficGraphic.segment_outline_type_e type) {
		if (array == null || array.isEmpty()) {
			return;
		}
		List<TrafficSegment> cache = new ArrayList<TrafficSegment>();
		int nCount = array.size();
		TrafficSegment last = array.get(0);
		TrafficSegment current;
		int i = 1;
		for (; i < nCount; i++) {
			String curStatus = "0";
			String lastStatus = "0";
			current = array.get(i);
			if (type == TrafficGraphic.segment_outline_type_e.up_segment_outline) {
				curStatus = current.up_traffic_status;
				lastStatus = last.up_traffic_status;
			} else if (type == TrafficGraphic.segment_outline_type_e.down_segment_outline) {
				curStatus = current.down_traffic_status;
				lastStatus = last.down_traffic_status;
			} else if (type == TrafficGraphic.segment_outline_type_e.total_segment_outline) {
				curStatus = current.traffic_status;
				lastStatus = last.traffic_status;
			}
			// 如果当前点不需要标名字，且状态和上一点一致，则不需要绘制该点，合并两点信息
			if (curStatus.equals(lastStatus) && isEmpty(last.endText)
					&& isEmpty(current.startText)) {
				last.vertex_count = current.vertex_count;
				last.endText = current.endText;
			} else {
				cache.add(last);
				last = current;
			}
		}
		// 信息处理完成后，last未加入cache中，需要加入一次
		if (i == nCount) {
			cache.add(last);
		}
		array.clear();
		array.addAll(cache);
		cache = null;
	}

	void initScale(int w, int h) {
		w = Math.min(w, h);
		float deseniy = w * 1f / ROAD_GRAPHIC_WIDTH_DEF;
		ROAD_GRAPHIC_WIDTH_NOINTERVAL = ROAD_GRAPHIC_WIDTH_DEF
				- ROAD_GRAPHIC_INTERVAL_DEF * 2;
		ROAD_GRAPHIC_WIDTH = ROAD_GRAPHIC_WIDTH_DEF * deseniy;
		ROAD_GRAPHIC_INTERVAL = ROAD_GRAPHIC_INTERVAL_DEF * deseniy;
		// ROAD_GRAPHIC_LINE_WIDTH *= deseniy;
		ROAD_GRAPHIC_WIDTH_NOINTERVAL = ROAD_GRAPHIC_WIDTH
				- ROAD_GRAPHIC_INTERVAL * 2;
		TrafficGraphic.setGap(deseniy);
	}

	void linearSmooth3(List<Vetrux> in) {
		List<Vetrux> out = new ArrayList<Vetrux>();
		if (in == null || in.size() < 3)
			return;
		int len = in.size();
		out.add(in.get(0));
		for (int i = 1; i < len - 1; i++) {
			Vetrux per = in.get(i - 1);
			Vetrux cur = in.get(i);
			Vetrux next = in.get(i + 1);
			double x = (per.x + cur.x + next.x) / 3;
			double y = (per.y + cur.y + next.y) / 3;
			out.add(new Vetrux(x, y));
		}
		out.add(in.get(len - 1));
		in.clear();
		in.addAll(out);
		out.clear();
	}

	private static boolean isEmpty(String str) {
		return str == null || "".equals(str) || "".equals(str.trim());
	}
}
